//
//  VOCWordTest.m
//  iVoc
//
//  Created by Wallace Wu on 09-3-24.
//  Copyright 2009 Sonic Solutions. All rights reserved.
//

#import "VOCWordTest.h"
#import "NSArray+VOCExtentions.h"
#include <stdlib.h>

NSString *pausedTestName = @"iVocPausedTest";

unsigned long long gSize = 0;;
NSTimeInterval gDate = 0;
VOCWordTest *gPausedTest = nil;

@interface VOCWordTest(private)

-(void)generateChoicesAndAnswers;
+(NSString*)pausedTestPath;

@end

@implementation VOCWordTest(private)
+(NSString*)pausedTestPath
{
    NSString *result = nil;
    NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
    
    if([documentPaths count] >0 )
    {
        result = [(NSString*)[documentPaths objectAtIndex:0] stringByAppendingPathComponent:pausedTestName];
    }
    
    return result;
}

-(void)generateChoicesAndAnswers
{
    NSArray *wordsWithSpecifiedLanguage = [self.currentList.data filteredWordsWithExplantionLanguage:self.testLanguage];
    VOCWordData *currentWord = (VOCWordData*)[wordsWithSpecifiedLanguage objectAtIndex:currentWordIndex];
    
    // pick an right choice
    VOCWordExp *currentExp = [[currentWord.explanations filteredExplanationsWithLanguage:self.testLanguage] objectAtIndex:arc4random()%[currentWord.explanations count]];
    
    NSMutableArray *choices = [[NSMutableArray alloc] initWithCapacity:self.choiceLimit];
    
    NSUInteger len = [wordsWithSpecifiedLanguage count];
    
    // initialization
    for (NSUInteger i = 0; i < len; i++) {
        seeds[i] = i;
    }
    
    // begin to shuffle
    for (NSUInteger i = len-1; i > 0; i--) {
        NSUInteger number = arc4random()%i;
        
        //swap the numbers
        NSUInteger tmp = seeds[i];
        seeds[i] = seeds[number];
        seeds[number] = tmp;
    }
    
    //now we have a shuffled vector, proceed to generate our choices
    NSUInteger i, index;
    for (i = 0; i < len; i++){
        //stop if we have all we want
        if([choices count] == self.choiceLimit-1)
            break;
        
        index = seeds[i];
        if(index == currentWordIndex)
            continue;
        VOCWordData *oneWord = [wordsWithSpecifiedLanguage objectAtIndex:index];
        
        for (VOCWordExp *exp in oneWord.explanations) {
            if(exp.function == currentExp.function)
            {
                [choices addObject:exp];
                break;
            }
        }
    }
    
    //put the right answer in a "right" place :)
    rightChoice = arc4random()%([choices count]+1);
    [choices insertObject:currentExp atIndex:self.rightChoice]; 
    
    // job done
    [_currentChoices release];
    _currentChoices = [choices copy];
    [choices release];
}

@end


@implementation VOCWordTest

@dynamic    choiceLimit;
@synthesize currentList;
@synthesize rightTimes;
@synthesize wrongTimes;
@synthesize testLanguage;
@dynamic hasEndTest;
@dynamic currentChoices;

-(VOCWordData*)currentWord
{
    return [self.currentList.data objectAtIndex:currentWordIndex];
}

-(void)setChoiceLimit:(NSUInteger)aLimit
{
    if(currentWordIndex == VOC_WORD_TEST_INVALID_INDEX)
    {
        choiceLimit = aLimit;
    }
}

-(NSUInteger)choiceLimit
{
    return choiceLimit;
}

-(NSArray*)currentChoices
{
    //simply return the variable, we`ll generate them in other place
    return [[_currentChoices copy] autorelease];
}

-(NSUInteger)rightChoice
{
    //simply return the variable, we`ll generate them in other place
    return rightChoice;
}

-(void)startTest
{
    if(currentWordIndex == VOC_WORD_TEST_INVALID_INDEX)
    {
        currentWordIndex = 0;
        rightTimes = 0;
        wrongTimes = 0;
    }

    [self generateChoicesAndAnswers];
}

-(BOOL)hasEndTest
{
    if(currentWordIndex >= [self.currentList.data count]-1)
    {
        return YES;
    }
    return NO;
}

-(void)stopTest
{
    currentWordIndex = VOC_WORD_TEST_INVALID_INDEX;
    rightChoice = VOC_WORD_TEST_INVALID_CHOICE;
    _currentChoices = nil;
    
    if(self == [VOCWordTest pausedTest])
    {
        [[NSFileManager defaultManager]  removeItemAtPath:[VOCWordTest pausedTestPath] error:NULL];
    }
}

-(BOOL)next
{   
    if( [self hasEndTest] )
        return NO;
    
    hasMadeChoice = NO;
    currentWordIndex ++;
    
    [self generateChoicesAndAnswers];
    
    return YES;
}

-(BOOL)makeChoice:(NSUInteger)index
{
    BOOL ret = NO;
    if(index == rightChoice)
    {
        if(!hasMadeChoice)
        {   
            rightTimes ++;
        }
        ret = YES;
    }
    else
    {
        if(!hasMadeChoice)
        {
            wrongTimes ++;
        }
    }
    
    hasMadeChoice = YES;
    return ret;
}


-(BOOL)isInTest
{
    return currentWordIndex != VOC_WORD_TEST_INVALID_INDEX;
}

+(BOOL)hasPausedTest
{
    return [self pausedTest] != nil;
}

+(VOCWordTest*)pausedTest
{
    if(![[NSFileManager defaultManager] fileExistsAtPath:[self pausedTestPath]])
    {
        return nil;
    }
    
    NSDictionary *attributes = [[NSFileManager defaultManager] fileAttributesAtPath:[self pausedTestPath] traverseLink:NO];
    NSNumber *fileSize = [attributes objectForKey:NSFileSize];
    NSDate *modifiedDate = [attributes objectForKey:NSFileModificationDate];
    if([fileSize unsignedLongLongValue] != gSize || gDate != [modifiedDate timeIntervalSince1970])
    {
        [gPausedTest release];
        gPausedTest = [(VOCWordTest*)[NSKeyedUnarchiver unarchiveObjectWithFile:[self pausedTestPath]] retain];
        
        gSize = [fileSize unsignedLongLongValue];
        gDate = [modifiedDate timeIntervalSince1970];
    }
    
    return gPausedTest;
}

-(VOCWORDLanguage)sourceLanguage
{
    return ((VOCWordData*)[self.currentList.data lastObject]).kind;
}

-(id)initWithWordList:(VOCWordList*)aList
{
    self = [super init];
    
    if(self)
    {
        self.currentList = aList;
        currentWordIndex = VOC_WORD_TEST_INVALID_INDEX;
        rightTimes = 0;
        wrongTimes = 0;
        rightChoice = VOC_WORD_TEST_INVALID_CHOICE;
        _currentChoices = nil;
        
        /* use an shuffled integer array for choices generation */
        seeds = (NSUInteger*)malloc(sizeof(NSUInteger)*[self.currentList.data count]);
    }
    
    return self;
}

-(void)dealloc
{
    free(seeds);
    [self.currentList release];
    [_currentChoices release];
    [super dealloc];
}


-(id)initWithCoder:(NSCoder *)encoder
{
    self = [super init];
    if(self)
    {
        NSString *pausedListName = [encoder decodeObjectForKey:@"currentList"];
        
        for (VOCWordList *list in [VOCWordList allWordLists:VOC_DEFAULT_WORDLIST_PATH]) {
            if([list.name isEqualToString:pausedListName])
            {
                self.currentList = list;
            }            
        }
        
        currentWordIndex = [encoder decodeIntegerForKey:@"currentWordIndex"];
        _currentChoices = [[encoder decodeObjectForKey:@"currentChoices"] retain];
        rightChoice = [encoder decodeIntegerForKey:@"rightChoice"];
        rightTimes = [encoder decodeIntegerForKey:@"rightTimes"];
        wrongTimes = [encoder decodeIntegerForKey:@"wrongTimes"];
        choiceLimit = [encoder decodeIntegerForKey:@"choiceLimit"];
        hasMadeChoice = [encoder decodeBoolForKey:@"hasMadeChoice"];
        testLanguage = [encoder decodeIntegerForKey:@"testLanguage"];
        
        /* use an shuffled integer array for choices generation */
        seeds = (NSUInteger*)malloc(sizeof(NSUInteger)*[self.currentList.data count]);
    }
    return self;
}

- (void)encodeWithCoder:(NSCoder *)encoder
{
    [encoder encodeObject:self.currentList.name forKey:@"currentList"];
    [encoder encodeObject:_currentChoices forKey:@"currentChoices"];
    [encoder encodeInteger:currentWordIndex forKey:@"currentWordIndex"];
    [encoder encodeInteger:rightTimes forKey:@"rightTimes"];
    [encoder encodeInteger:rightChoice forKey:@"rightChoice"];
    [encoder encodeInteger:wrongTimes forKey:@"wrongTimes"];
    [encoder encodeInteger:choiceLimit forKey:@"choiceLimit"];
    [encoder encodeInteger:testLanguage forKey:@"testLanguage"];
    [encoder encodeBool:hasMadeChoice forKey:@"hasMadeChoice"];
}

-(BOOL)pauseTest
{
    NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
    
    if([documentPaths count] >0 )
    {
        NSString *supportPath =(NSString*)[documentPaths objectAtIndex:0];
        NSFileManager *defaultManager = [NSFileManager defaultManager];
        
        if(![defaultManager fileExistsAtPath:supportPath])
        {
            [defaultManager createDirectoryAtPath:supportPath withIntermediateDirectories:YES attributes:nil error:NULL];
        }
        
        NSString *destPath = [(NSString*)[documentPaths objectAtIndex:0] stringByAppendingPathComponent:pausedTestName];
        
        return [NSKeyedArchiver archiveRootObject:self toFile:destPath];
    }
    
    return NO;
}
@end
